/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package managedbean.UserRoleManagement;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import javax.ejb.EJB;
import javax.faces.application.FacesMessage;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ManagedProperty;
import javax.faces.bean.ViewScoped;
import javax.faces.component.UIComponent;
import javax.faces.context.FacesContext;
import javax.faces.event.ActionEvent;
import javax.faces.validator.ValidatorException;
import javax.servlet.http.HttpServletRequest;
import managedbean.LoginAdmin.LoginManagerBean;
import managedbean.Workspace.WorkspaceManagerBean;
import merlion.common.entity.AccessRight;
import merlion.common.entity.SecurityRole;
import merlion.common.entity.Staff;
import merlion.common.session.stateless.SystemUserSessionBeanLocal;
import merlion.common.util.exception.NotExistException;
import merlion.common.util.exception.EntityExistException;
import merlion.common.util.exception.UpdateFailureException;

/**
 *
 * @author Zhang Ying
 */
@ManagedBean
@ViewScoped
public class UserRoleManagerBean {

    @ManagedProperty(value = "#{workspaceManagerBean}")
    private WorkspaceManagerBean workspaceManagerBean;
    @EJB
    private SystemUserSessionBeanLocal systemUserManager;
    private String roleName;
    private String department;
    private String statusMsg;
    private SecurityRole selectedRole;
    private Collection<Object> selectedRights;
    private AccessRight[] selectedAccessRights;
    private Collection<AccessRight> allAccessRights;
    private Collection<SecurityRole> allRoles;

    /** Creates a new instance of UserRoleManagerBean */
    public UserRoleManagerBean() {
        roleName = "";
        department = "";
    }

    public void addNewSecurityRole(ActionEvent event) {
        if (selectedRights.size() <= 0) {
            setStatusMsg("You should at least assign one access right to the new security role.");
            FacesContext.getCurrentInstance().addMessage(null,
                    new FacesMessage(FacesMessage.SEVERITY_ERROR, statusMsg, statusMsg));
        } else {
            try {
                Collection<AccessRight> selectedARs = new ArrayList<AccessRight>();
                for (Object itemId : selectedRights) {
                    selectedARs.add(systemUserManager.getAccessRight(Long.valueOf((String) itemId)));
                }
                systemUserManager.addNewSecurityRole(roleName, department, selectedARs);
                setStatusMsg("New security role is created successfully.");
                FacesContext.getCurrentInstance().addMessage(null,
                        new FacesMessage(FacesMessage.SEVERITY_INFO, statusMsg, statusMsg));
            } catch (EntityExistException ex) {
                setStatusMsg(ex.getMessage());
                FacesContext.getCurrentInstance().addMessage(null,
                        new FacesMessage(FacesMessage.SEVERITY_ERROR, statusMsg, statusMsg));
            } catch (Exception ex) {
                setStatusMsg(ex.getMessage());
                FacesContext.getCurrentInstance().addMessage(null,
                        new FacesMessage(FacesMessage.SEVERITY_ERROR, statusMsg, statusMsg));
            }
        }
    }

    // methods for viewing all roles
    public String selectRole(Long id) {
        setSelectedRole(systemUserManager.getSecurityRole(id));
        roleName = selectedRole.getRoleName();
        department = selectedRole.getDepartment();
        return null;
    }

    // methods for editing roles
    public void checkRolenameExists(FacesContext context, UIComponent component, Object value) throws ValidatorException {
        String nameInputed = (String) value;
        if (!nameInputed.equals(getRoleName()) && systemUserManager.checkRolenameExist(nameInputed)) {
            FacesMessage message = new FacesMessage(FacesMessage.SEVERITY_ERROR, "Role name exists", "Role name exists");
            throw new ValidatorException(message);
        }
    }

    public String initSelectedAccessRights(Long id) {
        setSelectedRole(systemUserManager.getSecurityRole(id));
        getSelectedAccessRights();
        roleName = selectedRole.getRoleName();
        department = selectedRole.getDepartment();
        return null;
    }

    public String editRole(Long id) {
        setSelectedRole(systemUserManager.getSecurityRole(id));
        roleName = selectedRole.getRoleName();
        department = selectedRole.getDepartment();
        return getRedirectPath("/UserRoleManagement/", "editRoleInfo") + "&roleId=" + id;
    }

    public String[] getAllDepartments() {
        Collection<String> deps = systemUserManager.getAllDepartments();
        String[] result = new String[deps.size()];
        int i = 0;
        for (String str : deps) {
            result[i] = str;
            i++;
        }
        return result;
    }

    public void updateEditRole(ActionEvent event) {
        selectedRole.setDepartment(department);
        selectedRole.setRoleName(roleName);
        // persist to database
        try {
            systemUserManager.updateSecurityRole(selectedRole);
            setStatusMsg("Security role is updated successfully.");
            updateCurrentStaff();
            FacesContext.getCurrentInstance().addMessage(null,
                    new FacesMessage(FacesMessage.SEVERITY_INFO, statusMsg, statusMsg));
        } catch (UpdateFailureException ex) {
            setStatusMsg(ex.getMessage());
            FacesContext.getCurrentInstance().addMessage(null,
                    new FacesMessage(FacesMessage.SEVERITY_ERROR, statusMsg, statusMsg));
        }
    }

    public void updateAccessRights(ActionEvent event) {
        Collection<AccessRight> updatedAccessRights = new ArrayList<AccessRight>();
        updatedAccessRights.addAll(Arrays.asList(selectedAccessRights));
        // persist to database
        try {
            if (updatedAccessRights.isEmpty()) {
                FacesContext.getCurrentInstance().addMessage(null,
                        new FacesMessage(FacesMessage.SEVERITY_ERROR, "Please select at least one access right", "Please select at least one access right"));
                return;
            }
            systemUserManager.updateSecurityRole(selectedRole, updatedAccessRights);
            updateCurrentStaff();
            setStatusMsg("Security role is updated successfully.");
            FacesContext.getCurrentInstance().addMessage(null,
                    new FacesMessage(FacesMessage.SEVERITY_INFO, statusMsg, statusMsg));
        } catch (Exception ex) {
            setStatusMsg(ex.getMessage());
            FacesContext.getCurrentInstance().addMessage(null,
                    new FacesMessage(FacesMessage.SEVERITY_ERROR, statusMsg, statusMsg));
        }
    }

    // methods for deleting roles
    public String deleteSelectedRole() {
        try {
            if (!systemUserManager.isAbleToDeleteRole(selectedRole)) {
                setStatusMsg("There is at least 1 staff that has and only has this security role. Thus, deletion failed.");
                FacesContext.getCurrentInstance().addMessage(null,
                        new FacesMessage(FacesMessage.SEVERITY_ERROR, "Unsuccessful", statusMsg));
                return null;
            }
            systemUserManager.deleteSecurityRole(selectedRole.getId());
            setAllRoles(systemUserManager.getAllSecurityRoles());
            setStatusMsg("Security role is deleted successfully.");
            updateCurrentStaff();
            FacesContext.getCurrentInstance().addMessage(null,
                    new FacesMessage(FacesMessage.SEVERITY_INFO, statusMsg, statusMsg));
        } catch (NotExistException ex) {
            setStatusMsg(ex.getMessage());
            FacesContext.getCurrentInstance().addMessage(null,
                    new FacesMessage(FacesMessage.SEVERITY_ERROR, statusMsg, statusMsg));
        }
        return null;
    }

    public AccessRight[] getSelectedAccessRights() {
        if (selectedRole != null) {
            Collection<AccessRight> arlsts = selectedRole.getAccessRights();
            AccessRight[] ars = new AccessRight[arlsts.size()];
            int i = 0;
            for (AccessRight ar : arlsts) {
                ars[i] = ar;
                i++;
            }
            selectedAccessRights = ars;
        }
        return selectedAccessRights;
    }

    public void setSelectedAccessRights(AccessRight[] selectedAccessRights) {
        this.selectedAccessRights = selectedAccessRights;
    }

    public Collection<SecurityRole> getAllRoles() {
        allRoles = systemUserManager.getAllSecurityRoles();
        return allRoles;
    }

    public void setAllRoles(Collection<SecurityRole> allRoles) {
        this.allRoles = allRoles;
    }

    public void setAllAccessRights(Collection<AccessRight> allAccessRights) {
        this.allAccessRights = allAccessRights;
    }

    public Collection<AccessRight> getAllAccessRights() {
        allAccessRights = systemUserManager.getAllAccessRights();
        return allAccessRights;
    }

    public Collection<Object> getSelectedRights() {
        return selectedRights;
    }

    public void setSelectedRights(Collection<Object> selectedRights) {
        this.selectedRights = selectedRights;
    }

    public SecurityRole getSelectedRole() {
        return selectedRole;
    }

    public void setSelectedRole(SecurityRole selectedRole) {
        this.selectedRole = selectedRole;
    }

    public String getStatusMsg() {
        return statusMsg;
    }

    public void setStatusMsg(String statusMsg) {
        this.statusMsg = statusMsg;
    }

    public String getDepartment() {
        if (department == null || department.equals("")) {
            HttpServletRequest request = (HttpServletRequest) FacesContext.getCurrentInstance().getExternalContext().getRequest();
            String parameter = request.getParameter("roleId");
            if (parameter != null) {
                Long id = Long.valueOf(parameter);
                setSelectedRole(systemUserManager.getSecurityRole(id));
                department = selectedRole.getDepartment();
            }
        }
        return department;
    }

    public void setDepartment(String department) {
        this.department = department;
    }

    public WorkspaceManagerBean getWorkspaceManagerBean() {
        return workspaceManagerBean;
    }

    public void setWorkspaceManagerBean(WorkspaceManagerBean workspaceManagerBean) {
        this.workspaceManagerBean = workspaceManagerBean;
    }

    public String getRoleName() {
        if (roleName == null || roleName.equals("")) {
            HttpServletRequest request = (HttpServletRequest) FacesContext.getCurrentInstance().getExternalContext().getRequest();
            String parameter = request.getParameter("roleId");
            if (parameter != null) {
                Long id = Long.valueOf(parameter);
                setSelectedRole(systemUserManager.getSecurityRole(id));
                roleName = selectedRole.getRoleName();
            }

        }
        return roleName;
    }

    public void setRoleName(String roleName) {
        this.roleName = roleName;
    }
    // private helper methods

    private String getRedirectPath(String parentPath, String actionPath) {
        return parentPath + actionPath + "?faces-redirect=true";
    }

    // update current staff
    private void updateCurrentStaff() {
        Staff s = systemUserManager.getStaff(workspaceManagerBean.getCurrentStaff().getId());
        workspaceManagerBean.setCurrentStaff(s);
        workspaceManagerBean.setLoggedUsername(s.getSystemUserAccount().getUsername());
        FacesContext.getCurrentInstance().getExternalContext().getSessionMap().put(LoginManagerBean.AUTH_KEY, s);
    }
}
